<template>
  <div class="editor-container">
    <!-- 图片上传组件 -->
    <el-upload
      :action="uploadUrl"
      :before-upload="handleBeforeUpload"
      :on-success="handleUploadSuccess"
      :on-error="handleUploadError"
      name="file"
      :show-file-list="false"
      :headers="headers"
      style="display: none"
      ref="upload"
      v-if="type === 'url'"
    ></el-upload>

    <!-- 富文本编辑器 -->
    <div class="quill-editor" ref="editor" :style="editorStyles"></div>

    <!-- 公式编辑弹窗 -->
    <el-dialog
      title="插入数学公式"
      :visible.sync="formulaDialogVisible"
      width="800px"
      @closed="handleDialogClose"
      append-to-body>
      <div class="formula-editor-container">
        <div class="formula-toolbar">
          <div class="symbol-categories">
            <el-tabs v-model="activeCategory" type="card">
              <el-tab-pane v-for="cat in symbolCategories"
                           :key="cat.name"
                           :label="cat.label"
                           :name="cat.name">
                <div class="symbol-group" v-for="group in cat.groups" :key="group.name">
                  <h4>{{ group.name }}</h4>
                  <div class="symbol-buttons">
                    <el-button
                      v-for="(symbol, idx) in group.symbols"
                      :key="idx"
                      @click="insertSymbol(symbol)"
                      size="mini">
                      {{ symbol.display || symbol.code }}
                    </el-button>
                  </div>
                </div>
              </el-tab-pane>
            </el-tabs>
          </div>
        </div>

        <div class="formula-preview">
          <div class="preview-container" ref="preview"></div>
          <div class="formula-input">
            <el-input
              ref="formulaInput"
              v-model="currentFormula"
              type="textarea"
              :rows="3"
              placeholder="输入LaTeX公式"
              @input="updatePreview"
            ></el-input>
          </div>
        </div>
      </div>

      <span slot="footer" class="dialog-footer">
        <el-button @click="formulaDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="confirmInsertFormula">插入</el-button>
      </span>
    </el-dialog>

    <!-- 新增表格弹窗 -->
    <el-dialog
      title="插入表格"
      :visible.sync="tableDialogVisible"
      width="400px"
      append-to-body>
      <div class="table-dialog">
        <div class="table-size">
          <el-input-number v-model="tableRows" :min="1" :max="10" label="行数"></el-input-number>
          <span class="separator">×</span>
          <el-input-number v-model="tableCols" :min="1" :max="10" label="列数"></el-input-number>
        </div>
        <el-button type="primary" @click="insertTable">插入表格</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import Quill from 'quill';
import 'quill/dist/quill.core.css';
import 'quill/dist/quill.snow.css';
import 'quill/dist/quill.bubble.css';
import { getToken } from "@/utils/auth";
import katex from 'katex';
import 'katex/dist/katex.min.css';
import 'element-ui/lib/theme-chalk/icon.css';

// Custom table module
const TableModule = {
  toolbarOptions: [['table']],
  handlers: {
    table: function() {
      this.quill.theme.tooltip.edit('table');
    }
  }
};

// Custom table blot
const BlockEmbed = Quill.import('blots/block/embed');

class TableCellBlot extends BlockEmbed {
  static create(value) {
    const node = super.create();
    node.setAttribute('contenteditable', true);
    node.setAttribute('class', 'ql-table-cell');
    node.setAttribute('data-row', value.row);
    node.setAttribute('data-col', value.col);
    return node;
  }

  static value(node) {
    return {
      row: node.getAttribute('data-row'),
      col: node.getAttribute('data-col')
    };
  }
}
TableCellBlot.blotName = 'table-cell';
TableCellBlot.tagName = 'td';

class TableRowBlot extends BlockEmbed {
  static create(value) {
    const node = super.create();
    node.setAttribute('class', 'ql-table-row');
    node.setAttribute('data-row', value);
    return node;
  }

  static value(node) {
    return node.getAttribute('data-row');
  }
}
TableRowBlot.blotName = 'table-row';
TableRowBlot.tagName = 'tr';

class TableBlot extends BlockEmbed {
  static create(value) {
    const node = super.create();
    node.setAttribute('class', 'ql-table');
    node.setAttribute('border', '1');
    node.setAttribute('style', 'border-collapse: collapse; width: 100%;');

    // Create rows and cells
    for (let i = 0; i < value.rows; i++) {
      const rowNode = document.createElement('tr');
      rowNode.setAttribute('class', 'ql-table-row');
      rowNode.setAttribute('data-row', i);

      for (let j = 0; j < value.cols; j++) {
        const cellNode = document.createElement('td');
        cellNode.setAttribute('class', 'ql-table-cell');
        cellNode.setAttribute('contenteditable', true);
        cellNode.setAttribute('data-row', i);
        cellNode.setAttribute('data-col', j);
        cellNode.style.border = '1px solid #ddd';
        cellNode.style.padding = '8px';
        cellNode.innerHTML = '<p><br></p>';
        rowNode.appendChild(cellNode);
      }

      node.appendChild(rowNode);
    }

    return node;
  }

  static value(node) {
    const rows = node.querySelectorAll('.ql-table-row').length;
    const cols = node.querySelector('.ql-table-row') ?
      node.querySelector('.ql-table-row').children.length : 0;
    return { rows, cols };
  }
}
TableBlot.blotName = 'table';
TableBlot.tagName = 'table';

// Register table blots
Quill.register({
  'formats/table': TableBlot,
  'formats/table-row': TableRowBlot,
  'formats/table-cell': TableCellBlot
});

// Custom formula blot
const Embed = Quill.import('blots/embed');
class FormulaBlot extends Embed {
  static create(value) {
    const node = super.create();
    node.dataset.value = value;
    katex.render(value, node, {
      throwOnError: false,
      errorColor: '#ff0000',
      displayMode: false
    });
    return node;
  }

  static value(node) {
    return node.dataset.value;
  }
}
FormulaBlot.blotName = 'formula';
FormulaBlot.className = 'ql-formula';
FormulaBlot.tagName = 'span';
Quill.register(FormulaBlot);

// Math symbols configuration
const SYMBOLS = {
  greekLetters: [
    { code: '\\alpha', display: 'α' },
    { code: '\\beta', display: 'β' },
    { code: '\\gamma', display: 'γ' },
    { code: '\\delta', display: 'δ' },
    { code: '\\epsilon', display: 'ε' },
    { code: '\\zeta', display: 'ζ' },
    { code: '\\eta', display: 'η' },
    { code: '\\theta', display: 'θ' },
    { code: '\\lambda', display: 'λ' },
    { code: '\\mu', display: 'μ' },
    { code: '\\pi', display: 'π' },
    { code: '\\sigma', display: 'σ' },
    { code: '\\omega', display: 'ω' }
  ],
  operators: [
    {code: '\\pm', display: '±'},
    {code: '\\times', display: '×'},
    {code: '\\div', display: '÷'},
    {code: '\\cdot', display: '·'},
    {code: '\\leq', display: '≤'},
    {code: '\\geq', display: '≥'},
    {code: '\\neq', display: '≠'},
    {code: '\\approx', display: '≈'},
    {code: '\\infty', display: '∞'}
  ],
  arrows: [
    {code: '\\rightarrow', display: '→'},
    {code: '\\leftarrow', display: '←'},
    {code: '\\Rightarrow', display: '⇒'},
    {code: '\\Leftarrow', display: '⇐'},
    {code: '\\leftrightarrow', display: '↔'},
    {code: '\\uparrow', display: '↑'},
    {code: '\\downarrow', display: '↓'}
  ],
  functions: [
    {code: '\\sin'},
    {code: '\\cos'},
    {code: '\\tan'},
    {code: '\\log'},
    {code: '\\ln'},
    {code: '\\lim'},
    {code: '\\sum'},
    {code: '\\prod'},
    {code: '\\int'},
    {code: '\\sqrt{x}'}
  ],
  structures: [
    {code: '\\frac{a}{b}', display: '分数 a/b'},
    {code: 'x^{n}', display: '上标 xⁿ'},
    {code: 'x_{n}', display: '下标 xₙ'},
    {code: '\\binom{n}{k}', display: '组合数 C(n,k)'},
    {code: '\\begin{matrix}a & b \\\\ c & d\\end{matrix}', display: '矩阵'}
  ]
};

export default {
  name: "EnhancedRichTextEditor",
  props: {
    value: {
      type: String,
      default: ""
    },
    height: {
      type: Number,
      default: null
    },
    minHeight: {
      type: Number,
      default: 300
    },
    readOnly: {
      type: Boolean,
      default: false
    },
    fileSize: {
      type: Number,
      default: 5
    },
    type: {
      type: String,
      default: "url"
    }
  },
  data() {
    return {
      tableDialogVisible: false,
      tableRows: 3,
      tableCols: 3,
      uploadUrl: process.env.VUE_APP_BASE_API + "/common/upload",
      headers: {
        Authorization: "Bearer " + getToken()
      },
      editor: null,
      currentValue: "",
      formulaDialogVisible: false,
      currentFormula: "",
      activeCategory: "letters",
      symbolCategories: [
        {
          name: "letters",
          label: "希腊字母",
          groups: [
            {name: "小写字母", symbols: SYMBOLS.greekLetters.slice(0, 8)},
            {name: "大写字母", symbols: SYMBOLS.greekLetters.slice(8)}
          ]
        },
        {
          name: "operators",
          label: "运算符",
          groups: [
            {name: "常用运算符", symbols: SYMBOLS.operators}
          ]
        },
        {
          name: "arrows",
          label: "箭头",
          groups: [
            {name: "常用箭头", symbols: SYMBOLS.arrows}
          ]
        },
        {
          name: "functions",
          label: "函数",
          groups: [
            {name: "数学函数", symbols: SYMBOLS.functions}
          ]
        },
        {
          name: "structures",
          label: "结构",
          groups: [
            {name: "常用结构", symbols: SYMBOLS.structures}
          ]
        }
      ],
      selectionRange: null
    };
  },
  computed: {
    editorStyles() {
      return {
        height: this.height ? `${this.height}px` : 'auto',
        minHeight: `${this.minHeight}px`
      };
    }
  },
  watch: {
    value(val) {
      if (val !== this.currentValue && this.editor) {
        this.currentValue = val || "";
        this.editor.clipboard.dangerouslyPasteHTML(this.currentValue);
      }
    },
    readOnly(val) {
      if (this.editor) {
        this.editor.enable(!val);
      }
    }
  },
  mounted() {
    this.initEditor();
  },
  beforeDestroy() {
    if (this.editor) {
      this.editor.off('text-change');
      this.editor = null;
    }
  },
  methods: {
    initEditor() {
      this.editor = new Quill(this.$refs.editor, {
        theme: "snow",
        bounds: document.body,
        modules: {
          toolbar: {
            container: [
              ["bold", "italic", "underline", "strike"],
              ["blockquote", "code-block"],
              [{header: [1, 2, 3, 4, 5, 6, false]}],
              [{list: "ordered"}, {list: "bullet"}],
              [{script: "sub"}, {script: "super"}],
              [{indent: "-1"}, {indent: "+1"}],
              [{direction: "rtl"}],
              [{size: ["small", false, "large", "huge"]}],
              [{color: []}, {background: []}],
              [{font: []}],
              [{align: []}],
              ["table"],
              ["clean"],
              ["link", "image", "video", "formula"]
            ],
            handlers: {
              formula: this.showFormulaDialog,
              table: this.showTableDialog
            }
          }
        },
        placeholder: "请输入内容...",
        readOnly: this.readOnly
      });

      this.editor.clipboard.dangerouslyPasteHTML(this.value || "");

      this.editor.on('text-change', () => {
        const html = this.$refs.editor.querySelector('.ql-editor').innerHTML;
        if (html !== this.currentValue) {
          this.currentValue = html;
          this.$emit('input', html);
          this.$emit('change', html);
        }
      });

      if (this.type === 'url') {
        const toolbar = this.editor.getModule('toolbar');
        toolbar.addHandler('image', this.handleImage);
      }
    },

    showTableDialog() {
      this.tableDialogVisible = true;
    },

    insertTable() {
      const range = this.editor.getSelection();
      if (range) {
        const tableValue = {
          rows: this.tableRows,
          cols: this.tableCols
        };

        this.editor.insertEmbed(range.index, 'table', tableValue, 'user');
        this.editor.setSelection(range.index + 1);
      }
      this.tableDialogVisible = false;
    },

    showFormulaDialog() {
      const range = this.editor.getSelection();
      if (range) {
        this.selectionRange = {
          index: range.index,
          length: range.length
        };
      }
      this.formulaDialogVisible = true;
      this.currentFormula = "";
      this.$nextTick(() => {
        this.$refs.formulaInput.focus();
        this.updatePreview();
      });
    },

    insertSymbol(symbol) {
      const textarea = this.$refs.formulaInput.$el.querySelector('textarea');
      const startPos = textarea.selectionStart;
      const endPos = textarea.selectionEnd;

      this.currentFormula =
        this.currentFormula.substring(0, startPos) +
        symbol.code +
        this.currentFormula.substring(endPos);

      this.$nextTick(() => {
        const newPos = startPos + symbol.code.length;
        textarea.setSelectionRange(newPos, newPos);
        textarea.focus();
        this.updatePreview();
      });
    },

    updatePreview() {
      if (this.$refs.preview) {
        try {
          katex.render(this.currentFormula || "\\text{输入公式预览}", this.$refs.preview, {
            throwOnError: false,
            displayMode: true
          });
        } catch (e) {
          this.$refs.preview.innerHTML = `<span style="color:red">${e.message}</span>`;
        }
      }
    },

    confirmInsertFormula() {
      if (this.currentFormula.trim()) {
        if (this.selectionRange) {
          const scrollTop = this.editor.scroll.domNode.scrollTop;

          if (this.selectionRange.length > 0) {
            this.editor.deleteText(
              this.selectionRange.index,
              this.selectionRange.length,
              'user'
            );
          }

          this.editor.insertEmbed(
            this.selectionRange.index,
            'formula',
            this.currentFormula.trim(),
            'user'
          );

          this.$nextTick(() => {
            const newPosition = this.selectionRange.index + 1;
            this.editor.setSelection(newPosition, 0, 'api');
            this.editor.scroll.domNode.scrollTop = scrollTop;
            this.editor.focus();
          });
        }
      }
      this.formulaDialogVisible = false;
    },

    handleDialogClose() {
      this.currentFormula = "";
      this.selectionRange = null;
    },

    handleImage() {
      this.$refs.upload.$el.querySelector('input[type="file"]').click();
    },

    handleBeforeUpload(file) {
      const validTypes = ["image/jpeg", "image/png", "image/gif", "image/webp"];
      const isValidType = validTypes.includes(file.type);
      const isValidSize = file.size / 1024 / 1024 < this.fileSize;

      if (!isValidType) {
        this.$message.error('请上传图片文件 (JPEG/PNG/GIF/WEBP)');
        return false;
      }

      if (!isValidSize) {
        this.$message.error(`图片大小不能超过 ${this.fileSize}MB`);
        return false;
      }

      return true;
    },

    handleUploadSuccess(res) {
      if (res.code === 200) {
        const range = this.editor.getSelection();
        this.editor.insertEmbed(
          range.index,
          'image',
          process.env.VUE_APP_BASE_API + res.fileName
        );
        this.editor.setSelection(range.index + 1);
      } else {
        this.$message.error(res.msg || '上传失败');
      }
    },

    handleUploadError(err) {
      console.error('上传错误:', err);
      this.$message.error('上传失败，请重试');
    },

    setContent(html) {
      this.currentValue = html || "";
      if (this.editor) {
        this.editor.clipboard.dangerouslyPasteHTML(this.currentValue);
      }
    },
    // 获取富文本纯文本
    getPlainText() {
      if (this.editor) {
        return this.editor.getText();
      }
      return '';
    }
  }
};
</script>

<style lang="scss">
.editor-container {
  position: relative;
  border-radius: 4px;
  overflow: hidden;

  .quill-editor {
    background: #fff;
    border: 1px solid #dcdfe6;
    border-radius: 4px;
    transition: border-color 0.2s;

    &:hover {
      border-color: #c0c4cc;
    }

    .ql-toolbar {
      border-top-left-radius: 4px;
      border-top-right-radius: 4px;
      border-bottom: 1px solid #dcdfe6;
    }

    .ql-container {
      border-bottom-left-radius: 4px;
      border-bottom-right-radius: 4px;
      font-size: 14px;
    }

    .ql-editor {
      min-height: inherit;
      padding: 12px 15px;
      line-height: 1.6;

      table {
        border-collapse: collapse;
        width: 100%;
        margin: 10px 0;

        td {
          border: 1px solid #ddd;
          padding: 8px;
          min-width: 50px;
          vertical-align: top;
        }
      }
    }
  }
}

.ql-formula {
  display: inline-block;
  vertical-align: middle;
  background: #f8f9fa;
  padding: 2px 5px;
  border-radius: 3px;
  margin: 0 2px;
  font-size: 0.9em;
}

.ql-snow .ql-toolbar button.ql-formula::after {
  content: "Σ";
  font-weight: bold;
}

/* 公式编辑弹窗样式 */
.formula-editor-container {
  display: flex;
  flex-direction: column;
  height: 500px;

  .formula-toolbar {
    flex: 0 0 auto;
    margin-bottom: 15px;

    .symbol-categories {
      .el-tabs__header {
        margin: 0;
      }

      .symbol-group {
        margin-bottom: 15px;

        h4 {
          margin: 10px 0 5px;
          font-size: 13px;
          color: #666;
        }

        .symbol-buttons {
          display: flex;
          flex-wrap: wrap;
          gap: 5px;

          .el-button {
            padding: 5px 8px;
            min-width: 40px;
          }
        }
      }
    }
  }

  .formula-preview {
    flex: 1;
    display: flex;
    flex-direction: column;
    border: 1px solid #ebeef5;
    border-radius: 4px;
    padding: 10px;

    .preview-container {
      flex: 1;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 15px;
      margin-bottom: 10px;
      border: 1px dashed #dcdfe6;
      border-radius: 4px;
      min-height: 80px;
      background: #f8f9fa;
      overflow: auto;

      .katex {
        font-size: 1.2em;
      }
    }

    .formula-input {
      flex: 0 0 auto;

      textarea {
        font-family: monospace;
      }
    }
  }
}

/* 响应式调整 */
@media (max-width: 768px) {
  .formula-editor-container {
    height: auto;
    flex-direction: column;

    .formula-toolbar {
      margin-bottom: 10px;
    }
  }
}

// 表格编辑弹窗样式
.table-dialog {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 15px;

  .table-size {
    display: flex;
    align-items: center;
    gap: 10px;

    .separator {
      font-size: 18px;
      color: #666;
    }
  }
}


/* 表格按钮图标 */
.ql-snow .ql-toolbar button.ql-table::before {
  font-family: element-icons !important;
  content: "\e6ce"; /* Element UI表格图标的Unicode编码 */
  font-size: 16px;
  line-height: 24px;
}

/* 调整按钮悬停样式 */
.ql-snow .ql-toolbar button.ql-table:hover::before {
  color: #06c;
}
</style>
